﻿using System;
using System.Collections.Specialized;
using System.Linq;
using System.Web.Hosting;
using System.Web.Security;
using InfoSite.Data;

namespace InfoSite.SiteMembership.Provider
{
	public class SiteRoleProvider : RoleProvider
	{
		private string _applicationName;
		public override string ApplicationName
		{
			get { return _applicationName; }
			set { _applicationName = value; }
		}

		public override void Initialize(string name, NameValueCollection config)
		{
			if (config == null)
				throw new ArgumentNullException("config");

			if (String.IsNullOrEmpty(name))
				name = "CustomRoleProvider";

			if (String.IsNullOrEmpty(config["description"]))
			{
				config.Remove("description");
				config.Add("description", "Custom Role Provider");
			}

			base.Initialize(name, config);

			_applicationName = GetConfigValue(config["applicationName"],
						  HostingEnvironment.ApplicationVirtualPath);

		}

		private string GetConfigValue(string configValue, string defaultValue)
		{
			if (String.IsNullOrEmpty(configValue))
				return defaultValue;

			return configValue;
		}

		public override void AddUsersToRoles(string[] emails, string[] roleNames)
		{
			foreach (string email in emails)
			{
				SiteUser siteUser = SiteUser.SearchByEmail(email);
				if (siteUser != null)
				{
					foreach (string rolename in roleNames)
					{
						AccessRole role = AccessRole.SearchByName(rolename);
						if (role != null)
						{
							if (!siteUser.AccessRoles.Contains(role) && siteUser.UserId != null && role.RoleId != null)
							{
								new SiteUserAccessRole(siteUser.UserId.Value, role.RoleId.Value).Save();
							}
						}
					}
				}
			}
		}

		public override void CreateRole(string roleName)
		{
			CreateRole(roleName, null);
		}

		public void CreateRole(string roleName, string roleDescription)
		{
			if (!RoleExists(roleName))
			{
				new AccessRole
					{
						Name = roleName,
						Description = roleDescription
					}.Save();
			}
		}

		public override bool DeleteRole(string roleName, bool throwOnPopulatedRole)
		{
			throw new NotImplementedException();
		}

		public override string[] FindUsersInRole(string roleName, string usernameToMatch)
		{
			AccessRole role = AccessRole.SearchByName(roleName);

			var clearSiteUsers =
				SiteUser.GetAllUsers().Where(siteUser => siteUser.Email.Equals(usernameToMatch, StringComparison.OrdinalIgnoreCase)).
					Where(siteUser => siteUser.AccessRoles.Any(tRole => tRole.CompareTo(role) == 0)).Select(x => x.Email);

			return clearSiteUsers.ToArray();
		}

		public override string[] GetAllRoles()
		{
			return AccessRole.GetAllRoles().Select(x => x.Name).ToArray();
		}

		public override string[] GetRolesForUser(string email)
		{
			SiteUser user = SiteUser.SearchByEmail(email);
			return user != null ? user.AccessRoles.Select(x => x.Name).ToArray() : null;
		}

		public override string[] GetUsersInRole(string roleName)
		{
			AccessRole role = AccessRole.SearchByName(roleName);

			var clearSiteUsers =
				SiteUser.GetAllUsers().Where(siteUser => siteUser.AccessRoles.Any(tRole => tRole.CompareTo(role) == 0)).Select(x => x.Email);

			return clearSiteUsers.ToArray();
		}

		public override bool IsUserInRole(string email, string roleName)
		{
			SiteUser siteUser = SiteUser.SearchByEmail(email);
			AccessRole role = AccessRole.SearchByName(roleName);
			if (siteUser != null && role != null)
			{
				return siteUser.AccessRoles.Contains(role);
			}
			throw new Exception("Ошибка при проверке ролей пользователя");
		}

		public override void RemoveUsersFromRoles(string[] emails, string[] roleNames)
		{
			foreach (string email in emails)
			{
				SiteUser siteUser = SiteUser.SearchByEmail(email);
				if (siteUser != null)
				{
					foreach (string rolename in roleNames)
					{
						AccessRole role = AccessRole.SearchByName(rolename);
						if (role != null)
						{
							if (siteUser.AccessRoles.Contains(role) && siteUser.UserId.HasValue && role.RoleId.HasValue)
							{
								SiteUserAccessRole.Get(role.RoleId.Value, siteUser.UserId.Value).Delete();
							}
						}
					}
				}
			}
		}

		public override bool RoleExists(string roleName)
		{
			return AccessRole.SearchByName(roleName) != null;
		}
	}
}
